package com.ssy.lingxi.pay.serviceimpl.eAccount;

import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderPaymentParameterEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.OrderPayChannelFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.PayChannelParameterFeignDetailVO;
import com.ssy.lingxi.order.api.model.vo.response.PaymentParameterFeignDetailVO;
import com.ssy.lingxi.pay.api.dto.request.eAccount.EAccountQueryRequest;
import com.ssy.lingxi.pay.entity.allInPay.AllInPay;
import com.ssy.lingxi.pay.entity.allInPay.AllInPayAttach;
import com.ssy.lingxi.pay.repository.allInPay.AllInPayAttachRepository;
import com.ssy.lingxi.pay.repository.allInPay.AllInPayRepository;
import com.ssy.lingxi.pay.service.eAccount.IEAccountService;
import com.ssy.lingxi.pay.utils.WeChatPayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 会员资金账户
 *
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/7/21
 */
@Service
public class EAccountServiceImpl implements IEAccountService {

    @Resource
    private AllInPayRepository allInPayRepository;

    @Resource
    private AllInPayAttachRepository allInPayAttachRepository;

    @Resource
    private OrderFeignService orderFeignService;

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 查询e账户主表
     */
    @Override
    public AllInPay getAccountDetail(UserLoginCacheDTO sysUser) {
        return allInPayRepository.findFirstByMemberIdAndMemberRoleId(sysUser.getMemberId(), sysUser.getMemberRoleId());
    }

    /**
     * 查询e账户附属表
     */
    @Override
    public AllInPayAttach getAccountAttachDetail(String bizUserId) {
        return allInPayAttachRepository.findFirstByBizUserId(bizUserId);
    }

    /**
     * 查询会员资金账户
     */
    @Override
    public AllInPay getAccountDetail(Long id) {
        return allInPayRepository.findById(id).orElse(null);
    }

    /**
     * 查询e账户
     *
     * @param pageVO               分页实体
     * @param eAccountQueryRequest 查询参数
     */
    @Override
    public Page<AllInPay> getPlatFormEAccountList(PageVO pageVO, EAccountQueryRequest eAccountQueryRequest) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        return allInPayRepository.findAll(getSpecification(eAccountQueryRequest), page);
    }

    /**
     * 冻结/解冻e账户的会员状态
     *
     * @param memberId     会员id
     * @param memberRoleId 会员角色id
     * @param memberStatus 会员状态
     */
    @Override
    public void updateMemberAssetAccount(Long memberId, Long memberRoleId, Integer memberStatus) {
        AllInPay allInPay = allInPayRepository.findFirstByMemberIdAndMemberRoleId(memberId, memberRoleId);
        if (allInPay != null) {
            allInPay.setMemberStatus(memberStatus);
            allInPayRepository.saveAndFlush(allInPay);
        }
    }

    /**
     * 构建查询条件
     *
     * @param eAccountQueryRequest 接口参数
     * @return 查询条件
     */
    private Specification<AllInPay> getSpecification(EAccountQueryRequest eAccountQueryRequest) {
        return (Specification<AllInPay>) (root, query, criteriaBuilder) -> {
            Predicate finalConditions = criteriaBuilder.conjunction();

            String memberName = eAccountQueryRequest.getMemberName();
            Long memberRoleId = eAccountQueryRequest.getMemberRoleId();
            Integer memberType = eAccountQueryRequest.getMemberType();
            Integer memberStatus = eAccountQueryRequest.getMemberStatus();
            Integer accountStatus = eAccountQueryRequest.getAccountStatus();

            //会员名称
            if (StringUtils.hasLength(memberName)) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.like(root.get("memberName").as(String.class), "%" + memberName + "%"));
            }
            //会员角色id
            if (memberRoleId != null && memberRoleId > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberRoleId").as(Long.class), memberRoleId));
            }
            //会员类型
            if (memberType != null && memberType > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberType").as(Integer.class), memberType));
            }
            //会员状态
            if (memberStatus != null && memberStatus > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("memberStatus").as(Integer.class), memberStatus));
            }
            //账号状态
            if (accountStatus != null && accountStatus > 0) {
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("accountStatus").as(Integer.class), accountStatus));
            }
            return finalConditions;
        };
    }

    /**
     * 获取微信参数
     *
     * @param jsCode 微信小程序code
     */
    @Override
    public Map<String, String> getWechatParam(String jsCode) {
        //通过小程序获取openId
        String merchantId = "";
        String appId = "";
        String appKey = "";
        //从订单服务查询支付参数
        OrderPayChannelFeignVO orderPayChannelFeignVO = new OrderPayChannelFeignVO();
        orderPayChannelFeignVO.setPayChannel(OrderPayChannelEnum.ALLIN_WECHAT);
        Wrapper<PaymentParameterFeignDetailVO> parameterResult = orderFeignService.findPlatformPaymentParameters(orderPayChannelFeignVO);
        if (parameterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(parameterResult.getCode(), parameterResult.getMessage());
        }
        if (CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
            throw new BusinessException(ResponseCode.ALLINPAY_WECHAT_APPLET_NOT_EXIST);
        }
        List<PayChannelParameterFeignDetailVO> parameters = parameterResult.getData().getParameters();
        for (PayChannelParameterFeignDetailVO p : parameters) {
            if (p.getParameter().equals(OrderPaymentParameterEnum.ALLIN_WECHAT_APPLET_APP_ID)) {
                appId = p.getValue();
            } else if (p.getParameter().equals(OrderPaymentParameterEnum.ALLIN_WECHAT_APPLET_APP_KEY)) {
                appKey = p.getValue();
            } else if (p.getParameter().equals(OrderPaymentParameterEnum.ALLIN_WECHAT_MERCHANT_ID)) {
                merchantId = p.getValue();
            }
        }
        //获取openId
        String param = "appid=" + appId + "&secret=" + appKey + "&js_code=" + jsCode + "&grant_type=" + WeChatPayUtil.GRANT_TYPE;
        String resultStr = WeChatPayUtil.httpsRequest(WeChatPayUtil.loginUrl, "POST", param);
        Map<String, String> resultMap = (Map<String, String>) JSONUtil.toBean(resultStr, Map.class);
        String openId = resultMap.get("openid");
        if (org.apache.commons.lang.StringUtils.isEmpty(openId)) {
            throw new BusinessException(ResponseCode.PAY_E_ACCOUNT_OPENID_EXCEPTION);
        }
        //定义返回map
        Map<String, String> map = new HashMap<>();
        map.put("openId", openId);
        map.put("merchantId", merchantId);
        map.put("subAppId", appId);

        return map;
    }

    /**
     * 获取微信subAppId
     *
     * @return subAppId
     */
    @Override
    public String getWechatSubAppId() {
        String appId = "";
        //从订单服务查询支付参数
        OrderPayChannelFeignVO orderPayChannelFeignVO = new OrderPayChannelFeignVO();
        orderPayChannelFeignVO.setPayChannel(OrderPayChannelEnum.ALLIN_WECHAT);
        Wrapper<PaymentParameterFeignDetailVO> parameterResult = orderFeignService.findPlatformPaymentParameters(orderPayChannelFeignVO);
        if (parameterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            throw new BusinessException(parameterResult.getCode(), parameterResult.getMessage());
        }
        if (CollectionUtils.isEmpty(parameterResult.getData().getParameters())) {
            throw new BusinessException(ResponseCode.ALLINPAY_WECHAT_APPLET_NOT_EXIST);
        }
        List<PayChannelParameterFeignDetailVO> parameters = parameterResult.getData().getParameters();
        for (PayChannelParameterFeignDetailVO p : parameters) {
            if (p.getParameter().equals(OrderPaymentParameterEnum.ALLIN_WECHAT_APPLET_APP_ID)) {
                appId = p.getValue();
            }
        }
        return appId;
    }
}

